#!/user/bin/env python3
# -*- coding: utf-8 -*-
"""
--------------------------------------
    Author:     JiChao_Song
    Date  :     2021/11/12 13:05
    Desc  :
--------------------------------------
"""
import datetime
from base64 import b64decode

import jwt

from common.utils.log_utils import logger
from person.models.person import Application
from platform_auth import settings
from platform_auth.settings import JWT_EXPIRATION_DELTA, SECRET_KEY


class JwtUtil:

    def __init__(self, secret: str = SECRET_KEY, token: str = None):
        self.secret = secret
        self.token = token

    def generate_jwt(self, payload: dict, expire: datetime = None):
        if expire is None:
            expire = JWT_EXPIRATION_DELTA
        _payload = {'exp': expire, 'iat': datetime.datetime.now(), }
        _payload.update(payload)
        logger.info(f'payload {_payload}')
        return jwt.encode(payload = _payload, key = self.secret)

    def verify_jwt(self):
        try:

            if self.token:
                payload = jwt.decode(jwt = self.token, key = self.secret, algorithms = ['HS256'])
            else:
                payload = None
        except jwt.PyJWTError as e:

            payload = None
        return payload

    def get_user_id(self):
        data = self.verify_jwt()
        logger.info(data)
        if data:
            return data.get('id')
        else:
            return None

    def get_user_id_and_username(self):
        data = self.verify_jwt()
        if data:
            return data.get('id'), data.get('username')
        return None, None


class AuthJwt(JwtUtil):

    def __init__(self, request=None):
        self.appId = request.headers.copy().get('Appid') if request is not None else settings.SERVER_APPID
        token = request.headers.copy().get('Accesstoken') if request is not None else None
        super().__init__(secret = self.secret_key(), token = token)

    def secret_key(self):

        queryset = Application.objects.filter(appId = self.appId, deleted = False).first()

        if not queryset:
            return ''
        else:
            return queryset.appSecret


class AuthJwtWithHeaders(JwtUtil):

    def __init__(self, headers: dict):
        appId = headers.get('Appid') if headers is not None else None
        token = headers.get('Accesstoken') if headers is not None else None

        if appId is None:
            appId = settings.SERVER_APPID
        self.appId = appId
        super().__init__(secret = self.secret_key(), token = token)

    def secret_key(self):

        queryset = Application.objects.filter(appId = self.appId, deleted = False).first()

        if not queryset:
            return ''
        else:
            return queryset.appSecret


import time
from django.core import signing
import hashlib
from django.core.cache import cache

HEADER = {'typ': 'JWP', 'alg': 'default'}
KEY = 'CHEN_FENG_YAO'
SALT = 'www.lanou3g.com'
TIME_OUT = 30 * 60  # 30min


def encrypt(obj):
    """加密"""
    value = signing.dumps(obj, key=KEY, salt=SALT)
    value = signing.b64_encode(value.encode()).decode()
    return value


def decrypt(src):
    """解密"""
    src = signing.b64_decode(src.encode()).decode()
    raw = signing.loads(src, key=KEY, salt=SALT)
    print(type(raw))
    return raw


def create_token(username):
    """生成token信息"""
    # 1. 加密头信息
    header = encrypt(HEADER)
    # 2. 构造Payload
    payload = {"username": username, "iat": time.time()}
    payload = encrypt(payload)
    # 3. 生成签名
    md5 = hashlib.md5()
    md5.update(("%s.%s" % (header, payload)).encode())
    signature = md5.hexdigest()
    token = "%s.%s.%s" % (header, payload, signature)
    # 存储到缓存中
    cache.set(username, token, TIME_OUT)
    return token


def get_payload(token):
    payload = str(token).split('.')[1]
    payload = decrypt(payload)
    return payload


# 通过token获取用户名
def get_username(token):
    payload = get_payload(token)
    return payload['username']
    pass


def check_token(token):
    username = get_username(token)
    last_token = cache.get(username)
    if last_token:
        return last_token == token
    return False
